﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace OOLib
{
   /// <summary>
   /// Represents the environment for a desktop component 
   /// </summary>
   /// <remarks>
   /// Frames are the anchors for the office components and they are the components' link to the outside world. 
   /// They create a skeleton for the whole office api infrastructure by building frame hierarchys. 
   /// These hierarchies contains all currently loaded documents and make it possible to walk during these trees. 
   /// A special service Desktop can(!) combine different of such trees to a global one which life time will be controlled by it. 
   /// </remarks>
   public class Frame : Component
   {
      #region Constructors

      /// <summary>
      /// Constructor
      /// </summary>
      /// <remarks>
      /// After using this constructor, the ComObj must be set manually!
      /// </remarks>
      public Frame() :
         base()
      { }

      /// <summary>
      /// Constructor
      /// </summary>
      /// <param name="comObject">COM object</param>
      public Frame(object comObject) :
         base(comObject)
      { }

      #endregion

      #region XFrame

      /// <summary>
      /// Is called to initialize the frame within a window - the container window. 
      /// </summary>
      /// <param name="window">The new container window</param>
      /// <remarks>
      /// This window will be used as parent for the component window and to support some UI relevant features of the frame service. 
      /// Note: Re-parenting mustn't supported by a real frame implementation! It's designed for initializing - not for setting. 
      /// This frame will take over ownership of the window refered from xWindow. 
      /// Thus, the previous owner is not allowed to dispose this window anymore. 
      /// !!! Not tested !!!
      /// </remarks>
      public void Initialize(Window window)
      {
         CheckDisposed();
         InvokeMethod("initialize", window.ComObj);
      }

      /// <summary>
      /// Gets the container window of the frame. 
      /// </summary>
      /// <remarks>
      /// Normally this is used as the parent window of the component window. 
      /// </remarks>
      public Window ContainerWindow
      {
         get
         {
            CheckDisposed();
            return GetObjectWrapper<Window>(InvokeMethod("getContainerWindow"));
         }
      }

      /// <summary>
      /// gets or sets the frame container that created this frame.
      /// </summary>
      /// <remarks>
      /// Only the creator is allowed to call this method. 
      /// But creator doesn't mean the implementation which creates this instance ... it means the parent frame of the frame hierarchy. 
      /// Because; normaly a frame should be created by using the api and is neccessary for searches inside the tree (e.g. XFrame::findFrame()) 
      /// !!! Not tested !!!
      /// </remarks>
      public FramesSupplier Creator
      {
         get
         {
            CheckDisposed();
            return GetObjectWrapper<FramesSupplier>(InvokeMethod("getCreator"));
         }
         set
         {
            CheckDisposed();
            InvokeMethod("setCreator", value.ComObj);
         }
      }

      /// <summary>
      /// Gets or sets the programmatic name of this frame
      /// </summary>
      /// <remarks>!!! Not tested !!!</remarks>
      public string Name
      {
         get
         {
            CheckDisposed();
            return (string)InvokeMethod("getName");
         }
         set
         {
            CheckDisposed();
            InvokeMethod("setName", value);
         }
      }

      /// <summary>
      /// Searches for a frame with the specified name. 
      /// </summary>
      /// <param name="targetFrameName">
      /// identify 
      /// •(a) a special target ("_blank","_self" ...) or
      /// •(b) any well known frame
      /// to search it inside the current hierarchy 
      /// </param>
      /// <param name="searchFlags">optional parameter to regulate search if no special target was used for TargetFrameName</param>
      /// <returns>Returns the found Frame</returns>
      /// <remarks>
      /// Frames may contain other frames (e.g., a frameset) and may be contained in other frames. 
      /// This hierarchy is searched with this method. First some special names are taken into account, i.e. "", "_self", "_top", "_blank" etc. 
      /// SearchFlags is ignored when comparing these names with TargetFrameName; further steps are controlled by SearchFlags. 
      /// If allowed, the name of the frame itself is compared with the desired one, and then ( again if allowed ) the method is called for all children of the frame. 
      /// Finally may be called for the siblings and then for parent frame (if allowed). 
      /// List of special target names: 
      /// ""/"_self" address the starting frame itself
      /// "_parent" address the direct parent frame only
      /// "_top" address the top frame of this subtree of the frametree
      /// "_blank" creates a new top frame
      /// If no frame with the given name is found, a new top frame is created; if this is allowed by a special flag FrameSearchFlag::CREATE. 
      /// The new frame also gets the desired name. 
      /// !!! Not tested !!!
      /// </remarks>
      public Frame FindFrame(string targetFrameName, int searchFlags)
      {
         CheckDisposed();
         return GetObjectWrapper<Frame>(InvokeMethod("findFrame", targetFrameName, searchFlags));
      }

      /// <summary>
      /// Gets if the frame is a top frame.
      /// </summary>
      /// <remarks>
      /// In general a top frame is the frame which is a direct child of a task frame or which does not have a parent. 
      /// Possible frame searches must stop the search at such a frame unless the flag FrameSearchFlag::TASKS is set. 
      /// !!! Not tested !!!
      /// </remarks>
      public bool IsTop
      {
         get
         {
            CheckDisposed();
            return (bool)InvokeMethod("isTop");
         }
      }

      /// <summary>
      /// Activates this frame and thus the component within. 
      /// </summary>
      /// <remarks>
      /// At first the frame sets itself as the active frame of its creator by calling XFramesSupplier::setActiveFrame(), 
      /// then it broadcasts an FrameActionEvent with FrameAction::FRAME_ACTIVATED. 
      /// The component within this frame may listen to this event to grab the focus on activation; for simple components this can be done by the FrameLoader. 
      /// Finally, most frames may grab the focus to one of its windows or forward the activation to a sub-frame. 
      /// !!! Not tested !!!
      /// </remarks>
      public void Activate()
      {
         CheckDisposed();
         InvokeMethod("activate");
      }

      /// <summary>
      /// Is called by the creator frame when another sub-frame gets activated.
      /// </summary>
      /// <remarks>
      /// At first the frame deactivates its active sub-frame, if any. Then broadcasts a FrameActionEvent with FrameAction::FRAME_DEACTIVATING.
      /// !!! Not tested !!!
      /// </remarks>
      public void Deactivate()
      {
         CheckDisposed();
         InvokeMethod("deactivate");
      }

      /// <summary>
      /// Gets if the frame is active.
      /// </summary>
      /// <remarks>!!! Not tested !!!</remarks>
      public bool IsActive
      {
         get
         {
            CheckDisposed();
            return (bool)InvokeMethod("isActive");
         }
      }

      /// <summary>
      /// Sets a new component into the frame or release an existing one from a frame.
      /// </summary>
      /// <param name="componentWindow">
      /// The window of the new component or NULL for release.
      /// A valid component window should be a child of the frame container window. 
      /// </param>
      /// <param name="controller">
      /// the controller of the new component or NULL for release.
      /// Simple components may implement a ::com::sun::star::awt::XWindow only. In this case no controller must be given here. 
      /// </param>
      /// <returns>
      /// true if setting of new component or release of an existing one was successfully.
      /// false otherwise (especialy, if an existing controller disagree within his XController::suspend() call) 
      /// </returns>
      /// <remarks>!!! Not tested !!!</remarks>
      public bool SetComponent(Window componentWindow, Controller controller)
      {
         CheckDisposed();
         return (bool)InvokeMethod("setComponent", componentWindow.ComObj, controller.ComObj);
      }

      /// <summary>
      /// Provides access to the component window 
      /// </summary>
      /// <returns>The current visible component in this frame or NULL if no one currently exist</returns>
      /// <remarks>
      /// Note: Don't dispose this window - the frame is the owner of it.
      /// !!! Not tested !!!
      /// </remarks>
      public Window GetComponentWindow()
      {
         CheckDisposed();
         return GetObjectWrapper<Window>(InvokeMethod("getComponentWindow"));
      }

      /// <summary>
      /// Gets the controller.
      /// </summary>
      /// <remarks>
      /// Note: Don't dispose it - the frame is the owner of it. Use XController::getFrame() to dispose the frame after 
      /// you the controller agreed with a XController::suspend() call.
      /// !!! Not tested !!!
      /// </remarks>
      public Controller Controller
      {
         get
         {
            CheckDisposed();
            return GetObjectWrapper<Controller>(InvokeMethod("getController"));
         }
      }

      /// <summary>
      /// Notifies the frame that the context of the controller within this frame changed (i.e. the selection). 
      /// </summary>
      /// <remarks>
      /// According to a call to this interface, the frame calls XFrameEventListener::frameAction with FrameAction::CONTEXT_CHANGED to all 
      /// listeners which are registered using XFrame::addFrameActionListener. For external controllers this event can be used to requery dispatches. 
      /// !!! Not tested !!!
      /// </remarks>
      public void ContextChanged()
      {
         CheckDisposed();
         InvokeMethod("contextChanged");
      }

      /// <summary>
      /// Registers an event listener, which will be called when certain things happen to the components within this frame or within sub-frames of this frame. 
      /// </summary>
      /// <param name="listener">Specifies the listener which will be informed</param>
      /// <remarks>
      /// E.g., it is possible to determine instantiation/destruction and activation/deactivation of components.
      /// !!! Not tested !!!
      /// </remarks>
      public void AddFrameActionListener(object listener)
      {
         CheckDisposed();
         InvokeMethod("addFrameActionListener", listener);
      }

      /// <summary>
      /// Unregisters an event listener
      /// </summary>
      /// <param name="listener">Specifies the listener which will not be informed any longer.</param>
      /// <remarks>!!! Not tested !!!</remarks>
      public void RemoveFrameActionListener(object listener)
      {
         CheckDisposed();
         InvokeMethod("removeFrameActionListener", listener);
      }

      #endregion

      #region properties

      /// <summary>
      /// Gets or sets the UI title on/from the frame container window.
      /// </summary>
      /// <remarks>
      /// It depends from the type of the frame container window. If it is a system task window all will be OK. 
      /// Otherwise the title can't be set. Setting/getting of the pure value of this property must be possible in every case. 
      /// Only showing on the UI can be fail.
      /// !!! Not tested !!!
      /// </remarks>
      public string Title 
      { 
         get
         {
            CheckDisposed();
            return (string)GetProperty("Title");
         }
         set
         {
            CheckDisposed();
            SetProperty("Title", value);
         }
      }

      /// <summary>
      /// Gets or sets the dispatch recorder of the frame.
      /// </summary>
      /// <remarks>
      /// Such recorder can be used to record dispatch requests. The supplier contains a dispatch recorder and provide 
      /// the functionality to use it for any dispatch object from outside which supports the interface XDispatch. 
      /// A supplier is available only, if recording was enabled. That means: if somewhere whish to enable recoding 
      /// on a frame he must set a supplier with a recorder object inside of it. Every user of dispatches has to check 
      /// then if such supplier is available at this frame property. If value of this property is NULL he must call 
      /// XDispatch::dispatch() on the original dispatch object. If it's a valid value he must use the supplier by 
      /// calling his method XDispatchRecorderSupplier::dispatchAndRecord() with the original dispatch object as argument. 
      /// Note: It's not recommended to cache an already getted supplier. Because there exist no possibility to check for enabled/disabled recording then. 
      /// !!! Not tested !!!
      /// </remarks>
      public ComObjectWrapper RecorderSupplier
      {
         //todo implement property type DispatchRecorderSupplier
         get
         {
            CheckDisposed();
            return GetObjectWrapper<ComObjectWrapper>(GetProperty("RecorderSupplier"));
         }
         set
         {
            CheckDisposed();
            SetProperty("RecorderSupplier", value.ComObj);
         }
      }

      /// <summary>
      /// Gets or sets the LayoutManager of the frame.
      /// </summary>
      /// <remarks>1!!! Not tested !!!</remarks>
      public ComObjectWrapper LayoutManager
      {
         //todo implement property type DispatchRecorderSupplier
         get
         {
            return GetObjectWrapper<ComObjectWrapper>(GetProperty("LayoutManager"));
         }
         set
         {
            SetProperty("LayoutManager", value.ComObj);
         }
      }

      #endregion
   }
}
